import os
import importlib
import inspect
import logging
from typing import Dict, List, Type, Optional

logger = logging.getLogger("Plugin")

class Plugin:
    """插件基类
    
    所有插件必须继承此类并实现必要的方法
    """
    
    # 插件元数据
    name = "base_plugin"
    description = "基础插件类"
    version = "1.0.0"
    author = "Unknown"
    
    def __init__(self, app=None):
        self.app = app
        self.enabled = True
    
    def initialize(self) -> bool:
        """初始化插件
        
        在应用程序启动时调用
        
        Returns:
            bool: 初始化是否成功
        """
        return True
    
    def shutdown(self) -> None:
        """关闭插件
        
        在应用程序关闭时调用
        """
        pass
    
    def enable(self) -> bool:
        """启用插件
        
        Returns:
            bool: 是否成功启用
        """
        self.enabled = True
        return True
    
    def disable(self) -> bool:
        """禁用插件
        
        Returns:
            bool: 是否成功禁用
        """
        self.enabled = False
        return True
    
    @property
    def is_enabled(self) -> bool:
        """插件是否已启用"""
        return self.enabled


class PluginManager:
    """插件管理器
    
    负责加载、初始化和管理插件
    """
    
    def __init__(self, app=None):
        self.app = app
        self.plugins: Dict[str, Plugin] = {}
        self.plugin_dirs = [
            os.path.join(os.path.dirname(__file__), "plugins")
        ]
    
    def add_plugin_directory(self, directory: str) -> None:
        """添加插件目录
        
        Args:
            directory: 插件目录路径
        """
        if os.path.isdir(directory) and directory not in self.plugin_dirs:
            self.plugin_dirs.append(directory)
            logger.info(f"已添加插件目录: {directory}")
    
    def discover_plugins(self) -> List[Type[Plugin]]:
        """发现所有可用的插件类
        
        Returns:
            List[Type[Plugin]]: 插件类列表
        """
        plugin_classes = []
        
        # 确保插件目录存在
        for plugin_dir in self.plugin_dirs:
            if not os.path.exists(plugin_dir):
                os.makedirs(plugin_dir)
                logger.info(f"创建插件目录: {plugin_dir}")
        
        # 从所有插件目录加载插件
        for plugin_dir in self.plugin_dirs:
            logger.info(f"从 {plugin_dir} 加载插件")
            
            # 遍历目录中的所有Python文件
            for filename in os.listdir(plugin_dir):
                if filename.endswith(".py") and not filename.startswith("_"):
                    module_name = filename[:-3]  # 去掉.py后缀
                    module_path = os.path.join(plugin_dir, filename)
                    
                    try:
                        # 动态导入模块
                        spec = importlib.util.spec_from_file_location(module_name, module_path)
                        if spec and spec.loader:
                            module = importlib.util.module_from_spec(spec)
                            spec.loader.exec_module(module)
                            
                            # 查找模块中的所有Plugin子类
                            for name, obj in inspect.getmembers(module):
                                if (inspect.isclass(obj) and 
                                    issubclass(obj, Plugin) and 
                                    obj is not Plugin):
                                    plugin_classes.append(obj)
                                    logger.info(f"发现插件: {obj.name} ({obj.description})")
                    except Exception as e:
                        logger.error(f"加载插件 {module_name} 失败: {str(e)}")
        
        return plugin_classes
    
    def load_plugins(self) -> None:
        """加载并初始化所有插件"""
        plugin_classes = self.discover_plugins()
        
        for plugin_class in plugin_classes:
            try:
                # 实例化插件
                plugin = plugin_class(self.app)
                plugin_name = plugin.name
                
                # 初始化插件
                if plugin.initialize():
                    self.plugins[plugin_name] = plugin
                    logger.info(f"插件 {plugin_name} v{plugin.version} 已加载")
                else:
                    logger.warning(f"插件 {plugin_name} 初始化失败")
            except Exception as e:
                logger.error(f"加载插件 {plugin_class.name} 时出错: {str(e)}")
    
    def get_plugin(self, name: str) -> Optional[Plugin]:
        """获取指定名称的插件
        
        Args:
            name: 插件名称
            
        Returns:
            Optional[Plugin]: 插件实例，如果不存在则返回None
        """
        return self.plugins.get(name)
    
    def enable_plugin(self, name: str) -> bool:
        """启用插件
        
        Args:
            name: 插件名称
            
        Returns:
            bool: 是否成功启用
        """
        plugin = self.get_plugin(name)
        if plugin:
            return plugin.enable()
        return False
    
    def disable_plugin(self, name: str) -> bool:
        """禁用插件
        
        Args:
            name: 插件名称
            
        Returns:
            bool: 是否成功禁用
        """
        plugin = self.get_plugin(name)
        if plugin:
            return plugin.disable()
        return False
    
    def shutdown_all(self) -> None:
        """关闭所有插件"""
        for name, plugin in self.plugins.items():
            try:
                plugin.shutdown()
                logger.info(f"插件 {name} 已关闭")
            except Exception as e:
                logger.error(f"关闭插件 {name} 时出错: {str(e)}")
        
        self.plugins.clear()

# 创建插件目录
def ensure_plugin_directory():
    """确保插件目录存在"""
    plugin_dir = os.path.join(os.path.dirname(__file__), "plugins")
    if not os.path.exists(plugin_dir):
        try:
            os.makedirs(plugin_dir, exist_ok=True)
            logger.info(f"创建插件目录: {plugin_dir}")
            
            # 创建__init__.py文件
            init_file = os.path.join(plugin_dir, "__init__.py")
            with open(init_file, 'w') as f:
                f.write("# 插件目录\n")
            
            logger.info("创建插件目录初始化文件")
        except Exception as e:
            logger.error(f"创建插件目录失败: {str(e)}")
            # 尝试使用备用目录
            plugin_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "plugins")
            if not os.path.exists(plugin_dir):
                os.makedirs(plugin_dir, exist_ok=True)
                logger.info(f"创建备用插件目录: {plugin_dir}")
                
                # 创建__init__.py文件
                init_file = os.path.join(plugin_dir, "__init__.py")
                with open(init_file, 'w') as f:
                    f.write("# 插件目录\n")
    
    return plugin_dir